package org.framework.lazy.cloud.network.heartbeat.client.netty.proxy.http.handler;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import org.framework.lazy.cloud.network.heartbeat.common.decoder.TransferDecoder;
import org.framework.lazy.cloud.network.heartbeat.common.encoder.TransferEncoder;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.protocol.actuator.AbstractNettyHttpProxyActuator;
import org.framework.lazy.cloud.network.heartbeat.protocol.actuator.NettyHttpProxyActuator;
import org.framework.lazy.cloud.network.heartbeat.protocol.handler.NettyHttpProxyBackendHandler;
import org.framework.lazy.cloud.network.heartbeat.protocol.route.ProxyRoute;
import org.framework.lazy.cloud.network.heartbeat.protocol.route.RouteContext;
import org.framework.lazy.cloud.network.heartbeat.protocol.route.RouteType;
import org.springframework.stereotype.Component;
import org.wu.framework.core.exception.RuntimeExceptionFactory;
import org.wu.framework.core.utils.ObjectUtils;

/**
 * 客户端代理
 * 客户端：本地代理、远程服务端代理、远程客户端代理
 */
@Component
public class NettyClientHttpProxy extends AbstractNettyHttpProxyActuator implements NettyHttpProxyActuator {

//    private final ChannelTypeAdapter channelTypeAdapter;
//
//    public NettyClientHttpProxy(ChannelTypeAdapter channelTypeAdapter) {
//        this.channelTypeAdapter = channelTypeAdapter;
//    }

    /**
     * 是否允许代理
     *
     * @param host 访问主机地址
     * @param port 访问端口
     */
    @Override
    public boolean support(String host, int port) {
        return ObjectUtils.isNotEmpty(RouteContext.getRoute(host, String.valueOf(port)));
    }

    /**
     * 获取代理通道
     *
     * @param originChannel   原始通道
     * @param fullHttpRequest 消息体
     * @param host            访问主机地址
     * @param port            访问端口
     */
    @Override
    public Channel createProxyChannelThenSend(Channel originChannel, FullHttpRequest fullHttpRequest, String host, int port) {
        ProxyRoute route = RouteContext.getRoute(host, String.valueOf(port));
        RouteType routeType = route.getRouteType();
        if (RouteType.LOCAL.equals(routeType)) {
            Bootstrap b = new Bootstrap();
            b.group(originChannel.eventLoop())
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(
                                    new TransferDecoder(Integer.MAX_VALUE, 1024 * 1024 * 10),
                                    new TransferEncoder(),
                                    new NettyHttpProxyBackendHandler()
                            );
                        }
                    });
            ChannelFuture f = b.connect(host, port);
            Channel proxyChannel = f.channel();
            f.addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    ChannelAttributeKeyUtils.buildNextChannel(proxyChannel, originChannel);
                    ChannelAttributeKeyUtils.buildNextChannel(originChannel, proxyChannel);
                    doSend(proxyChannel, fullHttpRequest);
                } else {
                    originChannel.close();
                }
            });
            return proxyChannel;
        } else if (RouteType.CLIENT_PROXY_SEVER.equals(routeType)) {
            // 创建服务端端链接
//            NettyHttpClientProxyServerTransferSocket.buildTransferServer(internalNetworkClientPermeateClientVisitor,originChannel);
            // 发送数据
            // 返回响应结果

        } else if (RouteType.CLIENT_PROXY_CLIENT.equals(routeType)) {
            // 获取客户端ID
            // 创建服务端链接
            // 服务端创建客户端链接
            // 连接成功后发送数据
            // 发送数据进行响应数据接收

        }

        RuntimeExceptionFactory.of("执行异常");
        return null;
    }


}
